package xquery;

import java.util.ArrayList;
import java.util.LinkedList;
import java.util.Queue;

import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

import xquery.XPathData.Type;


public class XPathComposedExp extends XPathExp {
	public static enum XPathOperator
	{
		UNION, DIRECT, ALL, FILTER, IS, EQUAL, AND, OR;
		
		public static XPathOperator string2op(String s) {
			if(s.equals("/"))
				return DIRECT;
			else if (s.equals("//"))
				return ALL;
			else if (s.equals("is"))
				return IS;
			else if (s.equals("eq"))
				return EQUAL;
			else
				return null;
		}
	};
	
	XPathOperator[] op;
	XPathExp[] operand;
	
	@Override
	public XPathData eval(XQContext context, ArrayList<Node> currentNodeList) {
		XPathData result = operand[0].eval(context, currentNodeList);
		
		for(int i=0;i<op.length;i++) {
			switch(op[i]) {
			case UNION:
				ArrayList<Node> resultNodeList2 = operand[i+1].eval(context, currentNodeList).getList();
				result.getList().addAll(resultNodeList2);
				break;
			case DIRECT:
				result.set(operand[i+1].eval(context, result.getList()).getList());
				break;
			case ALL:
				ArrayList<Node> resultNodeList = getDescendants(context, result.getList());
				result.set(operand[i+1].eval(context, resultNodeList).getList());
				break;
			case FILTER:
				result.set(evalFilter(context, result.getList(), operand[i+1]));
				break;
			case IS:
				result.set(result.is(operand[i+1].eval(context, currentNodeList)));
				break;
			case EQUAL:
				result.set(result.eq(operand[i+1].eval(context, currentNodeList)));
				break;
			case AND:
				result.set(result.getBool() && operand[i+1].eval(context, currentNodeList).getBool());
			case OR:
				result.set(result.getBool() || operand[i+1].eval(context, currentNodeList).getBool()); 
			}
		}
		
		return result;
	}
	
	private ArrayList<Node> evalFilter(XQContext context,ArrayList<Node> input, XPathExp filter)
	{		
		ArrayList<Node> result = new ArrayList<Node>();

		for(Node node : input)
		{
			ArrayList<Node> currentNodeList = new ArrayList<Node>();
			currentNodeList.add(node);

			if(filter.eval(context, currentNodeList).getBool())
			{
				result.add(node);
			}
		}
		return result;
	}
	public String toString()
	{
		StringBuffer sb  = new StringBuffer("");
		sb.append(operand[0]);
		for(int i = 1;i<operand.length;i++)
		{
			if(op[i-1] == XPathOperator.DIRECT)
			{
				sb.append("\\");
			}
			else
			{
				sb.append("\\\\");
			}
			sb.append(operand[i]);
		}
		return sb.toString();
	}

}
